home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 22 / AACD 22.iso / AACD / Sound / mhi_dev / MASPro / Source / mhi_MASPro.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-04-29  |  13.6 KB  |  633 lines

  1. /* MHI DCR MAS-Player library */
  2.  
  3. #include <clib/exec_protos.h>
  4. #include <clib/alib_protos.h>
  5. #include <clib/cia_protos.h>
  6. #include <clib/misc_protos.h>
  7. #include <clib/dos_protos.h>
  8.  
  9. #include <exec/libraries.h>
  10. #include <exec/types.h>
  11. #include <exec/memory.h>
  12. #include <exec/lists.h>
  13. #include <exec/interrupts.h>
  14. #include <hardware/intbits.h>
  15. #include <hardware/cia.h>
  16. #include <resources/cia.h>
  17. #include <resources/misc.h>
  18.  
  19. #include "mhi.h"
  20.  
  21. #pragma libbase MHIBase
  22.  
  23.  
  24. extern void dcr_pro_int();
  25. extern void SetupParPort();
  26. extern void SetVolume(register __d0 ULONG vol);
  27. extern void SetPrefactor(register __d0 UWORD prefac);
  28. extern void SetBass(register __d0 UWORD bass);
  29. extern void SetTreble(register __d0 UWORD treb);
  30.  
  31. /* volume
  32.  * first is loudest
  33.  * 21 total
  34.  */
  35.  
  36. ULONG voltab[21] = 
  37.     {0x80000,0x8DEB8,0x9A537,0xA5621,0xAF3CD,0xB8053,0xBFD92,0xC6D31,
  38.      0xCD0AD,0xD2958,0xD785E,0xDBECC,0xDFD91,0xE3583,0xE675F,0xE93CF,
  39.      0xEBB6A,0xEDEB6,0xEFE2C,0xF1A36,0xFFFFA};
  40.  
  41. /* prefactor
  42.  * first is quietest
  43.  * 16 total
  44.  */
  45.  
  46. UWORD preftab[16] = 
  47.     {0x8000,0x8E00,0x9A40,0xA580,0xAF40,0xB800,0xBFC0,0xC6C0,
  48.      0xCD00,0xD25C,0xD780,0xDC00,0xDFC0,0xE340,0xE680,0xE940};
  49.  
  50. /* bass
  51.  * 0x0000 (15) is normal
  52.  * 31 total
  53.  */
  54.  
  55. UWORD basstab[31] = 
  56.     {0x9E40,0xA280,0xA740,0xAC40,0xB180,0xB740,0xBD40,0xC3C0,
  57.      0xCA40,0xD180,0xD8C0,0xE040,0xE800,0xEFC0,0xF7C0,0x0000,
  58.      0x0800,0x1000,0x17C0,0x1F80,0x2700,0x2E40,0x3580,0x3C00,
  59.      0x4280,0x4880,0x4E40,0x5380,0x5880,0x5D40,0x6180};
  60.  
  61. /* treble
  62.  * 0x0000 (15) is normal
  63.  * 31 total
  64.  */
  65.  
  66. UWORD trebtab[31] = 
  67.     {0xB2C0,0xBB40,0xC180,0xC6C0,0xCBC0,0xD040,0xD500,0xD980,
  68.      0xDE00,0xE280,0xE7E0,0xEC00,0xF0C0,0xF5C0,0xFAC0,0x0000,
  69.      0x0540,0x0AC0,0x1040,0x1600,0x1C00,0x2200,0x2840,0x2EC0,
  70.      0x3540,0x3C00,0x42C0,0x49C0,0x5180,0x5840,0x5F80};
  71.  
  72. STRPTR DriverName        = "MAS Player Pro";
  73. STRPTR DriverVersion = "$VER: 1.2 Final (02/04/01)";
  74. STRPTR DriverAuthor    = "Paul Qureshi";
  75.  
  76. struct MPHandle
  77. {
  78.     APTR data;                /* current buffer node                 */
  79.     APTR endnode;            /* node at the end of the list     */
  80.     struct Task *task;    /* task that wants signals         */
  81.     ULONG mhisignal;        /* signal mask to use                 */
  82.     UBYTE status;            /* player status flags                */
  83.     UBYTE    oldstatus;        /* last status                            */
  84.  
  85.     UBYTE volume;
  86.     UBYTE panning;
  87.     UBYTE mixing;
  88.     UBYTE prefactor;
  89.     UBYTE bass;
  90.     UBYTE treble;
  91.     UBYTE mid;
  92. };
  93.  
  94. struct MPBufferNode
  95. {
  96.     struct MinNode    my_MinNode;
  97.     APTR    buffer;
  98.     APTR    pos;
  99.     ULONG    bytesleft;
  100. };
  101.  
  102. /* Prototypes */
  103.  
  104. APTR     MHIAllocDecoder    (register __a0 struct Task *task, register __d0 ULONG mhisignal);
  105. VOID     StartTimer            (struct freetimer *ft);
  106. BOOL     FindFreeTimer        (struct freetimer *ft, int preferA);
  107. BOOL     TryTimer                (struct freetimer *ft);
  108. VOID     MHIFreeDecoder        (register __a3 APTR handle);
  109. BOOL     MHIQueueBuffer        (register __a3 MPHandle *handle, register __a0 APTR buffer, register __d0 ULONG size);
  110. APTR    MHIGetEmpty            (register __a3 MPHandle *handle);
  111. UBYTE    MHIGetStatus        (register __a3 MPHandle *handle);
  112. VOID    MHIPlay                (register __a3 MPHandle *handle);
  113. VOID    MHIStop                (register __a3 MPHandle *handle);
  114. VOID    MHIPause                (register __a3 MPHandle *handle);
  115. ULONG    MHIQuery                (register __d1 ULONG query);
  116. VOID    MHISetParam            (register __a3 MPHandle *handle, register __d0 UWORD param, register __d1 ULONG value);
  117.  
  118. struct MinList BufList;
  119.  
  120. BOOL mhiallocated;
  121.  
  122. UBYTE *owner = NULL;
  123. struct Library *MiscBase = NULL;
  124.  
  125. /*
  126.  * CIA stuff
  127.  *
  128.  */
  129.  
  130. #define HICOUNT 0x0A
  131. #define LOCOUNT 0x00
  132.  
  133. #define STOPA_AND  CIACRAF_TODIN | CIACRAF_PBON | CIACRAF_OUTMODE | CIACRAF_SPMODE
  134. #define STOPB_AND  CIACRBF_ALARM | CIACRBF_PBON | CIACRBF_OUTMODE
  135.  
  136. #define STARTA_OR  CIACRAF_START
  137. #define STARTB_OR  CIACRBF_START
  138.  
  139. /*
  140.  * Structure which will be used to hold all relevant information about
  141.  * the cia timer we manage to allocate.
  142.  *
  143.  */
  144.  
  145. struct freetimer
  146. {
  147.     struct Library *ciabase;        /* CIA Library Base             */
  148.     ULONG  timerbit;                /* timer bit allocated          */
  149.     struct CIA *cia;                /* ptr to hardware              */
  150.     UBYTE *ciacr;                   /* ptr to control register      */
  151.     UBYTE *cialo;                   /* ptr to low byte of timer     */
  152.     UBYTE *ciahi;                   /* ptr to high byte of timer    */
  153.     struct Interrupt timerint;      /* Interrupt structure          */
  154.     UBYTE  stopmask;                /* Stop/set-up timer            */
  155.     UBYTE  startmask;               /* Start timer                  */
  156. };
  157.  
  158. struct CIA *ciaa = (struct CIA *)0xbfe001;
  159. struct CIA *ciab = (struct CIA *)0xbfd000;
  160.  
  161. struct freetimer ft;
  162.  
  163. /* --------------------------------------------------------------------- */
  164. /*                             Start of code                             */
  165. /* --------------------------------------------------------------------- */
  166.  
  167. APTR MHIAllocDecoder(register __a0 struct Task *task, register __d0 ULONG mhisignal)
  168. /* Allocate MHI. Open all needed resources etc, and be prepared
  169.     to output.
  170.  
  171.     *task is the task that wants signals
  172.     mhisignal is the signal mask to use
  173. */
  174. {
  175.     struct MPHandle *handle;
  176.     
  177.     if (!mhiallocated)
  178.         if ( handle = AllocMem(sizeof(MPHandle), MEMF_CLEAR) )
  179.         {
  180.             handle->task = task;
  181.             handle->mhisignal = mhisignal;
  182.             handle->status = MHIF_STOPPED;
  183.  
  184.             handle->volume        = 100;
  185.             handle->panning    = 50;
  186.             handle->mixing        = 50;
  187.             handle->prefactor    = 50;
  188.             handle->bass        = 50;
  189.             handle->treble        = 50;
  190.             handle->mid            = 50;
  191.  
  192.             SetVolume(voltab[0]);
  193.             SetPrefactor(preftab[0]);
  194.             SetBass(basstab[15]);
  195.             SetTreble(trebtab[15]);
  196.  
  197.             if ( MiscBase = (struct Library *)OpenResource(MISCNAME) )
  198.             {
  199.                 if ( ((owner = AllocMiscResource(MR_PARALLELPORT, "MHI")) == NULL)
  200.                 &&      ((owner = AllocMiscResource(MR_PARALLELBITS, "MHI")) == NULL) )
  201.                 {
  202.  
  203.                     SetupParPort();    // set par port bits
  204.  
  205.                     ft.timerint.is_Node.ln_Type     = NT_INTERRUPT;
  206.                     ft.timerint.is_Node.ln_Pri     = 0;
  207.                     ft.timerint.is_Node.ln_Name     = "MHI_MAS_Player_Pro";
  208.                     ft.timerint.is_Data                 = handle;
  209.                     ft.timerint.is_Code                 = dcr_pro_int;
  210.  
  211.                     if (FindFreeTimer(&ft,TRUE))
  212.                     {
  213.                         StartTimer(&ft);
  214.  
  215.                         /* setup main list */
  216.                         BufList.mlh_Head        = (struct MinNode *) &BufList.mlh_Tail;
  217.                         BufList.mlh_Tail        = 0;
  218.                         BufList.mlh_TailPred    = (struct MinNode *) &BufList.mlh_Head;
  219.                         mhiallocated = TRUE;
  220.                         return handle;
  221.                     }
  222.                     else
  223.                         return 0L;
  224.                 }
  225.                 else
  226.                     return 0L;
  227.             }
  228.             else
  229.                 return 0L;
  230.         }
  231.         else
  232.             return 0L;
  233.     else
  234.         return 0L;
  235. }
  236.  
  237. VOID MHIFreeDecoder(register __a3 APTR handle)
  238. /* Free MHI and all resources
  239. */
  240. {
  241.     APTR killednode;
  242.  
  243.     if (handle)
  244.     {
  245.         RemICRVector(ft.ciabase,ft.timerbit,&ft.timerint);
  246.         
  247.         FreeMem(handle, sizeof(MPHandle));
  248.         
  249.         FreeMiscResource(MR_PARALLELPORT);
  250.         FreeMiscResource(MR_PARALLELBITS);
  251.         
  252.         /* free buffer list */
  253.         while ( killednode = RemHead((struct List *)&BufList) )
  254.             FreeMem(killednode, sizeof(struct MPBufferNode));
  255.             
  256.         mhiallocated = FALSE;
  257.     }
  258. }
  259.  
  260. BOOL MHIQueueBuffer(register __a3 MPHandle *handle, register __a0 APTR buffer, register __d0 ULONG size)
  261. /* Add this buffer to the queue
  262. */
  263. {
  264.     struct MPBufferNode *newnode;
  265.     
  266.     if (!( newnode = AllocMem(sizeof(MPBufferNode), MEMF_CLEAR) ))
  267.         return FALSE;
  268.     else
  269.     {
  270.         newnode->buffer         = buffer;
  271.         newnode->pos            = buffer;
  272.         newnode->bytesleft     = size;
  273.         AddTail((struct List *)&BufList,(struct Node *)newnode);
  274.         handle->endnode = newnode;
  275.         
  276.         if (handle->data == 0)
  277.             handle->data = newnode;
  278.             
  279.         return TRUE;
  280.     }
  281. }
  282.  
  283. APTR MHIGetEmpty(register __a3 MPHandle *handle)
  284. /* Find the next empty buffer node and return the buffers address
  285. */
  286. {
  287.     struct MPBufferNode *mynode;
  288.     APTR temp = 0;
  289.     
  290.     mynode = (MPBufferNode *)BufList.mlh_Head;
  291.     
  292.     for (mynode = (MPBufferNode *)BufList.mlh_Head ; mynode->my_MinNode.mln_Succ ; mynode = (MPBufferNode *)mynode->my_MinNode.mln_Succ)
  293.         if (mynode->bytesleft == 0)
  294.             temp = mynode;
  295.             
  296.     mynode = temp;
  297.     
  298.     if ((APTR)mynode != &BufList && mynode != 0)
  299.     {
  300.         Remove((struct Node *)mynode);
  301.         temp = mynode->buffer;
  302.         FreeMem(mynode, sizeof(struct MPBufferNode));
  303.         return temp;
  304.     }
  305.     else
  306.         return 0L;
  307. }
  308.  
  309. UBYTE MHIGetStatus(register __a3 MPHandle *handle)
  310. /* Get the MHI players status flags
  311. */
  312. {
  313.     return handle->status;
  314. }
  315.  
  316. VOID MHIPlay(register __a3 MPHandle *handle)
  317. /* Set the player to play mode
  318. */
  319. {
  320.     handle->status = MHIF_PLAYING;
  321. }
  322.  
  323. VOID MHIStop(register __a3 MPHandle *handle)
  324. /* Stop the player and free all buffers
  325. */
  326. {
  327.     APTR killednode;
  328.  
  329.     handle->status = MHIF_STOPPED;
  330.     handle->data = 0;
  331.     /* free buffer list */
  332.     while ( killednode = RemHead((struct List *)&BufList) )
  333.         FreeMem(killednode, sizeof(struct MPBufferNode));    
  334. }
  335.  
  336. VOID MHIPause(register __a3 MPHandle *handle)
  337. /* Pause the player
  338. */
  339. {
  340.     if (handle->status == MHIF_PAUSED)            /* Unpause */
  341.         handle->status = MHIF_PLAYING;
  342.     else
  343.         if (handle->status == MHIF_PLAYING)        /* Pause */
  344.             handle->status = MHIF_PAUSED;
  345. }
  346.  
  347. ULONG MHIQuery(register __d1 ULONG query)
  348. /* Respond to a feature query from an application
  349. */
  350. {
  351.     switch (query)
  352.     {
  353.         case MHIQ_MPEG1: case MHIQ_MPEG2: case MHIQ_MPEG25:
  354.             return MHIF_SUPPORTED;
  355.             break;
  356.         
  357.         case MHIQ_MPEG4:
  358.             return MHIF_UNSUPPORTED;
  359.             break;
  360.             
  361.         case MHIQ_LAYER1:
  362.             return MHIF_UNSUPPORTED;
  363.             break;
  364.             
  365.         case MHIQ_LAYER2: case MHIQ_LAYER3:
  366.             return MHIF_SUPPORTED;
  367.             break;
  368.             
  369.         case MHIQ_VARIABLE_BITRATE:
  370.             return MHIF_SUPPORTED;
  371.             break;
  372.         
  373.         case MHIQ_JOINT_STERIO:
  374.             return MHIF_SUPPORTED;
  375.             break;
  376.             
  377.         case MHIQ_BASS_CONTROL: case MHIQ_TREBLE_CONTROL: case MHIQ_MID_CONTROL:
  378.             return MHIF_UNSUPPORTED;
  379.             break;
  380.             
  381.         case MHIQ_VOLUME_CONTROL: case MHIQ_PANNING_CONTROL: case MHIQ_CROSSMIXING:
  382.             return MHIF_UNSUPPORTED;
  383.             break;
  384.             
  385.         case MHIQ_IS_HARDWARE:
  386.             return MHIF_TRUE;
  387.             break;
  388.  
  389.         case MHIQ_IS_68K: case MHIQ_IS_PPC:
  390.             return MHIF_FALSE;
  391.             break;
  392.             
  393.         case MHIQ_DECODER_NAME:
  394.             return (ULONG) DriverName;
  395.             break;
  396.  
  397.         case MHIQ_DECODER_VERSION:
  398.             return (ULONG) DriverVersion;
  399.             break;
  400.             
  401.         case MHIQ_AUTHOR:
  402.             return (ULONG) DriverAuthor;
  403.             break;
  404.             
  405.         default:
  406.             return MHIF_UNSUPPORTED;
  407.             break;            
  408.     }
  409. }
  410.  
  411. VOID MHISetParam(register __a3 MPHandle *handle, register __d0 UWORD param, register __d1 ULONG value)
  412. /* Set decoder paramiter.
  413. */
  414. {
  415.     UBYTE calc;
  416.  
  417.     switch (param)
  418.     {
  419.         case MHIP_VOLUME:
  420.  
  421.             if (value != handle->volume)
  422.             {
  423.                 handle->oldstatus = handle->status;
  424.                 handle->status = MHIF_PAUSED;
  425.     
  426.                 handle->volume = value;
  427.                 calc = (float)(100 - value) * 0.2;
  428.                 if (calc > 20)
  429.                     calc = 20;
  430.                 if (calc < 0)
  431.                     calc = 0;
  432.                 SetVolume(voltab[calc]);
  433.         
  434.                 handle->status = handle->oldstatus;
  435.             }
  436.         
  437.             break;
  438.         
  439.         case MHIP_PANNING:
  440.  
  441.             if (value != handle->panning)
  442.             {
  443.                 handle->panning = value;
  444.             }
  445.             
  446.             break;
  447.  
  448.         case MHIP_CROSSMIXING:
  449.  
  450.             if (value != handle->mixing)
  451.             {
  452.                 handle->mixing = value;
  453.             }
  454.             
  455.             break;
  456.             
  457.         case MHIP_PREFACTOR:
  458.  
  459.             if (value != handle->prefactor)
  460.             {
  461.                 handle->prefactor = value;
  462.                 if (value > 50)
  463.                 {
  464.                     value -= 50;                            // only prefactors above 50
  465.                     if (value < 0)                        // are used by the MAS3507
  466.                         value = 0;
  467.                     calc = (float)value * .3;
  468.                     if (calc > 15)
  469.                         calc = 15;
  470.                     if (calc < 0)
  471.                         calc = 0;
  472.                 }
  473.                 else
  474.                 {
  475.                     calc=0;
  476.                 }
  477.                 SetPrefactor(preftab[calc]);
  478.             }
  479.             
  480.             break;
  481.  
  482.         case MHIP_BASS:
  483.  
  484.             if (value != handle->bass)
  485.             {
  486.                 handle->bass = value;
  487.                 calc = (float)value * 0.3;
  488.                 if (calc > 30)
  489.                     calc = 30;
  490.                 if (calc < 0)
  491.                     calc = 0;
  492.                 SetBass(basstab[calc]);
  493.             }
  494.  
  495.             break;
  496.  
  497.         case MHIP_TREBLE:
  498.  
  499.             if (value != handle->treble)
  500.             {
  501.                 handle->treble = value;
  502.                 calc = (float)value * 0.3;
  503.                 if (calc > 30)
  504.                     calc = 30;
  505.                 if (calc < 0)
  506.                     calc = 0;
  507.                 SetTreble(trebtab[calc]);
  508.             }
  509.  
  510.             break;
  511.  
  512.         case MHIP_MID:
  513.  
  514.             if (value != handle->mid)
  515.             {
  516.                 handle->mid = value;
  517.                 // SetMid(mid);
  518.             }
  519.  
  520.             break;
  521.  
  522.     }
  523.     
  524. }
  525.  
  526. void StartTimer(struct freetimer *ft)
  527. {
  528. register struct CIA *cia;
  529.  
  530. cia = ft->cia;
  531.  
  532. /* Note that there are differences between control register A,
  533.  * and B on each CIA (e.g., the TOD alarm bit, and INMODE bits.
  534.  */
  535.  
  536. if (ft->timerbit == CIAICRB_TA)
  537.     {
  538.     ft->ciacr = &cia->ciacra;       /* control register A   */
  539.     ft->cialo = &cia->ciatalo;      /* low byte counter     */
  540.     ft->ciahi = &cia->ciatahi;      /* high byte counter    */
  541.  
  542.     ft->stopmask = STOPA_AND;       /* set-up mask values   */
  543.     ft->startmask = STARTA_OR;
  544.     }
  545. else
  546.     {
  547.     ft->ciacr = &cia->ciacrb;       /* control register B   */
  548.     ft->cialo = &cia->ciatblo;      /* low byte counter     */
  549.     ft->ciahi = &cia->ciatbhi;      /* high byte counter    */
  550.  
  551.     ft->stopmask = STOPB_AND;       /* set-up mask values   */
  552.     ft->startmask = STARTB_OR;
  553.     }
  554.  
  555. Disable();
  556. *ft->ciacr &= ft->stopmask;
  557. Enable();
  558.  
  559. /* Clear signal bit - interrupt will signal us later */
  560. /* SetSignal(0L,1L<<ed->signal);
  561. */
  562.  
  563. *ft->cialo = LOCOUNT;
  564. *ft->ciahi = HICOUNT;
  565.  
  566. /* Turn on start bit - same bit for both A, and B control regs  */
  567.  
  568. Disable();
  569. *ft->ciacr |= ft->startmask;
  570. Enable();
  571. }
  572.  
  573.  
  574.  
  575. BOOL FindFreeTimer(struct freetimer *ft, int preferA)
  576. {
  577. //struct CIABase *ciaabase, *ciabbase;
  578. struct Library *ciaabase, *ciabbase;
  579.  
  580. ciaabase = OpenResource(CIAANAME);
  581. ciabbase = OpenResource(CIABNAME);
  582.  
  583. if (preferA)
  584.     {
  585.     ft->ciabase = ciaabase; /* library address  */
  586.     ft->cia     = ciaa;     /* hardware address */
  587.     }
  588. else
  589.     {
  590.     ft->ciabase = ciabbase; /* library address  */
  591.     ft->cia     = ciab;     /* hardware address */
  592.     }
  593.  
  594. if (TryTimer(ft))
  595.     return(TRUE);
  596.  
  597. if (!(preferA))
  598.     {
  599.     ft->ciabase = ciaabase; /* library address  */
  600.     ft->cia     = ciaa;     /* hardware address */
  601.     }
  602. else
  603.     {
  604.     ft->ciabase = ciabbase; /* library address  */
  605.     ft->cia     = ciab;     /* hardware address */
  606.     }
  607.  
  608. if (TryTimer(ft))
  609.     return(TRUE);
  610.  
  611. return(FALSE);
  612.  
  613. }
  614.  
  615.  
  616.  
  617. BOOL TryTimer(struct freetimer *ft)
  618. {
  619.  
  620. if (!(AddICRVector(ft->ciabase,CIAICRB_TA,&ft->timerint)))
  621.     {
  622.     ft->timerbit = CIAICRB_TA;
  623.     return(TRUE);
  624.     }
  625.  
  626. if (!(AddICRVector(ft->ciabase,CIAICRB_TB,&ft->timerint)))
  627.     {
  628.     ft->timerbit = CIAICRB_TB;
  629.     return(TRUE);
  630.     }
  631.  
  632. return(FALSE);
  633. }